﻿using System;

namespace SQLPXBase.Factory.Keys.KeyModels
{
    public class CoupledPK<T1, T2> : PrimaryKey
        where T1 : struct
        where T2 : struct
    {
        private T1? k1;
        private T2? k2;

        #region Constructors

        public CoupledPK()
        {
        }

        public CoupledPK(T1? k1, T2? k2):this()
        {
            this.k1 = k1;
            this.k2 = k2;
        }

        #endregion

        public override bool IsEmpty
        {
            get { return !(k1.HasValue || k2.HasValue); }
        }

        public override PrimaryKey DefaultValue
        {
            get { return new CoupledPK<T1, T2>(); }
        }

        public override object GetSingleValue
        {
            get { throw new NotImplementedException(); }
        }

        public override object[] GetValues
        {
            get { return IsEmpty ? null : new object[] {k1, k2}; }
        }

        public override void SetValues(object[] values)
        {
            CheckValues(values);

            try
            {
                k1 = (T1)values[0];
                k2 = (T2) values[1];
            }
            catch (Exception ex)
            {
                throw new PrimaryKeyException(ex.Message, ex);
            }
        }

        public override int KeyLength
        {
            get { return 2; }
        }

        public T1? Value1
        {
            get { return k1; }
        }
        public T2? Value2
        {
            get { return k2; }
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;

            if (obj.GetType() == this.GetType())
            {
                CoupledPK<T1, T2> tmp = (CoupledPK<T1, T2>) obj;

                if (tmp.IsEmpty && this.IsEmpty)
                    return true;

                if (Equals(tmp.Value1, this.Value1) && Equals(tmp.Value2, this.Value2))
                    return true;
            }

            return false;
        }
    }
}
